
/*******************************************************************************
 * buffesq.hpp - a disk based queue
 * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 ******************************************************************************/

#ifndef __BOQUE_BUFFESQ_HPP_2010__
#define __BOQUE_BUFFESQ_HPP_2010__

#include <sys/types.h>

#include <stdexcept>
#include <string>
#include <iostream>

#include <boost/thread/mutex.hpp>


namespace boque {


class BuffesQ
{

public:
    BuffesQ( const std::string& q_dir, u_int32_t file_size_threshold=0 );
    ~BuffesQ();

    void    push( const std::string& );

    std::string    pop( void );
    
    std::string    front( void );
    
    bool empty(); 

    void    push( const char*, size_t );

// friends:
    friend std::ostream& operator<<(std::ostream& os, BuffesQ& bufq);

private :
    BuffesQ( const boque::BuffesQ& );
    BuffesQ&    operator=( const boque::BuffesQ& );

private:

    struct  Location
    {
    public  :
        int32_t fileno;
        int32_t offset;

    public  :
        Location()
            : fileno(0), offset(0)
        {
        }
        Location( int32_t fn, int32_t off ) 
            :   fileno(fn), offset(off)
        {
        }

    public  :
        bool    operator==( const Location& rhs )
        {
            return  ((fileno == rhs.fileno) && (offset == rhs.offset));
        }
        bool    operator!=( const Location& rhs )
        {
            return  ((fileno != rhs.fileno) || (offset != rhs.offset));
        }

    };  //// struct Location

private :
    void    openStatusFile( void );
    void    openPushFile( void );
    void    openPopFile( void );
    void    closePopFile( void );
    void    closePushFile( void );
    void    closeStatusFile( void );

	int		getStatusFD( void );

    size_t  getStatusHeadOffset( void );
    size_t  getStatusTailOffset( void );

    void    updateStatusHeadLocation( void );
    void    updateStatusTailLocation( void );

    void    reloadStatusLocation( void );

    void    createDataFile( const std::string& filename );
    void    removeDataFile( int32_t file_id );

    int32_t getNextDataFileNo( int32_t fileno );

    void    enlargeBuffer( void );

    std::string    _front( void );
    
private :
    std::string _q_dir;
    std::string _status_file;

    Location    _head;
    Location    _tail;

    FILE*   _fp_status;
    FILE*   _fp_push;
    FILE*   _fp_pop;

    boost::mutex    _mutex_status;
    boost::mutex    _mutex_push;
    boost::mutex    _mutex_pop;

    char*   _buf_p;
    size_t  _buf_size;

    size_t  _file_size_threshold;
};	// class BuffesQ


}	// namespace boque

#endif /* __BOQUE_BUFFESQ_HPP_2010__*/

